package com.yonyou.ucf.mdf.core.uitemplate.service.impl;


import com.yonyou.iuap.context.InvocationInfoProxy;
import com.yonyou.iuap.formula.common.SpringContextHolder;
import com.yonyou.uap.tenant.service.itf.ITenantRoleUserService;
import com.yonyou.uap.tenantauth.entity.TenantRole;
import com.yonyou.ucf.mdd.common.constant.MddConstants;
import com.yonyou.ucf.mdd.common.model.uimeta.ui.View;
import com.yonyou.ucf.mdd.ext.bill.meta.model.TplSelectBO;
import com.yonyou.ucf.mdd.ext.bill.utils.ExtPropsUtil;
import com.yonyou.ucf.mdd.ext.consts.ConstantsProperties;
import com.yonyou.ucf.mdd.ext.core.AppContext;
import com.yonyou.ucf.mdd.ext.dubbo.DubboReferenceUtils;
import com.yonyou.ucf.mdd.ext.util.uimeta.ExtTenantUtil;
import com.yonyou.ucf.mdd.ext.util.union.MdfMapKeyUtil;
import com.yonyou.ucf.mdf.api.exceptions.MdfBusinessException;
import com.yonyou.ucf.mdf.api.uitemplate.dto.param.BillTemplateQureryParamDTO;
import com.yonyou.ucf.mdf.core.uitemplate.bo.MdfTplStdBO;
import com.yonyou.ucf.mdf.core.uitemplate.service.MdfBillTemplateQueryService;
import com.yonyou.ucf.mdf.core.uitemplate.service.MdfTemplateRunTimeService;
import com.yonyou.ucf.mdf.core.uitemplate.service.MdfUnionBillTemplateQueryService;
import com.yonyou.ucf.mdf.iris.exceptions.MdfIrisException;
import com.yonyou.ucf.mdf.iris.template.assign.service.MdfTemplateAssignService;
import com.yonyou.ucf.mdf.iris.template.org.dto.TemplateAssignDTO;
import com.yonyou.ucf.mdf.iris.template.org.dto.TemplateAssignQueryParamDTO;
import com.yonyou.ucf.mdf.iris.template.org.dto.TemplateOrgDTO;
import com.yonyou.ucf.mdf.iris.template.org.service.MdfTemplateLoadService;
import com.yonyou.ucf.mdf.iris.template.query.dto.MdfSingleTplQueryParam;
import com.yonyou.ucf.mdf.iris.template.query.dto.MdfTplItemDTO;
import com.yonyou.ucf.mdf.iris.template.query.dto.MdfTplQueryParam;
import com.yonyou.ucf.mdf.iris.template.query.service.MdfTemplateQueryService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 模板匹配
 *
 * @author xuli
 * @date 2021/12/10 下午2:30
 */
public class MdfTemplateRunTimeServiceImpl implements MdfTemplateRunTimeService {


    private static final int SERVICE_CURRENT_VERSION = 1;
    private static final Logger logger = LoggerFactory.getLogger(MdfTemplateRunTimeServiceImpl.class);

    /**
     * 模板类型
     */
    private static final String FIELD_EXT_NEXUS_TYPE = "nexusType";
    /**
     * 组织级模板
     */
    private static final String FIELD_EXT_ORG_TPL_ORG_ID = "orgTplOrgId";
    /**
     * 交易类型模板
     */
    private static final String FIELD_EXT_TRANS_TYPE_ID = "transTypeId";

    private static final String KEY_ORG_ID_DEFAULT = "666666";

    private static final String CONF_ENABLE_UINION_DOMAIN = "mdd.uimeta.prop.isMetaServer";

    @Override
    public int getCurrentVersion() throws MdfBusinessException {
        return SERVICE_CURRENT_VERSION;
    }

    @Override
    public MdfTplStdBO getSingleTpl(BillTemplateQureryParamDTO param){
        String billNo = param.getBillno();
        Long tplmode = param.getTplmode();
        Map<String, Object> extCondition = param.getExtParamMap();
        String orgId =param.getOrgId();

        String transtype = param.getTranstype();
        String extTranstype = param.getExtTranstype();
        //兼容交易类型数据，保证extTransType和transType值一致
        if (StringUtils.isEmpty(extTranstype)) {
            extTranstype = transtype;
        }
        if(StringUtils.isEmpty(transtype)){
            transtype = extTranstype;
        }
        if(StringUtils.isEmpty(transtype)){
            transtype = MdfMapKeyUtil.getMapStringValueByKey("transTypeId", extCondition);
            extTranstype =transtype;
        }

        String businessStepCode = param.getBusinessStepCode();
        String serviceCode = param.getServiceCode();
        if(StringUtils.isEmpty(serviceCode)) {
            serviceCode = AppContext.getThreadContext(MddConstants.PARAM_SERVICE_CODE);
        }
        String terminalType = param.getTerminalType();

        MdfTplStdBO tplStdDTO = new MdfTplStdBO();
        terminalType = StringUtils.isEmpty(terminalType) ? "1" : terminalType;
        if (billNo == null ) {
            //参数信息不全
            logger.error("单据类型存在为空，不支持查询");
            return null;
        }


        tplStdDTO.setTransType(transtype);
        /*预览态直接返回,这个应该框架处理，如果预览态传了也默认选模板，存在预览态嵌入其他页面其他需要选模板*/
        /**if(designPreview){
         tplStdDTO.setBranch("designPreview");
         return tplStdDTO;
         }*/
        // 执行查询
        List<View> viewList = listTplByParams(billNo, terminalType);
        if (CollectionUtils.isEmpty(viewList)) {
            if (Integer.parseInt(terminalType) > 2) {
                tplStdDTO.setHasMultiMode(false);
                //移动没模板时重查下pc模板
                viewList = listTplByParams(billNo, "1");
                if (CollectionUtils.isEmpty(viewList)) {
                    //查全部模板pc端一个也没有，那就只能返回空了
                    return null;
                }
                //唯一模板直接返
                if(viewList.size() == 1){
                    tplStdDTO.setBranch("pcSingleTpl");
                    tplStdDTO.setTplId(Long.valueOf(String.valueOf(viewList.get(0).getTplId())));
                    return tplStdDTO;
                }
                //如果当前单据没有移动端模板，但是非要一个模板就返回pc默认
                View defaultTpl = getDefaultTplByViewList(viewList);
                tplStdDTO.setBranch("defaultPCTpl");
                if(defaultTpl ==null){
                    defaultTpl = viewList.get(0);
                    tplStdDTO.setBranch("default0Tpl");
                }
                tplStdDTO.setTplId(Long.valueOf(String.valueOf(defaultTpl.getTplId())));
                if(defaultTpl.getcExtProps()!=null) {
                    Map<String, Object> cExtPropsMap = ExtPropsUtil.getExtProps(defaultTpl.getcExtProps());
                    tplStdDTO.setTransType(MdfMapKeyUtil.getMapStringValueByKey("transTypeId", cExtPropsMap));
                }
                return tplStdDTO;
            }else {
                //查全部模板pc端一个也没有，那就只能返回空了
                return null;
            }
        }

        if (viewList.size() == 1) {
            // 如果模板只查询了一个出来，直接返回了，其他的都不管
            tplStdDTO.setTplId(MdfMapKeyUtil.getLongValue(viewList.get(0).getTplId()));
            tplStdDTO.setBranch("singleTpl");
            tplStdDTO.setHasMultiMode(false);
            return tplStdDTO;
        }

        Set<Integer> modeSet = new HashSet<>();
        for (View view : viewList) {
            if(view.getTplMode()==null){
                continue;
            }
            modeSet.add(view.getTplMode());
        }
        if(modeSet.size()>1){
            /*存在多态*/
            tplStdDTO.setHasMultiMode(true);
        }

        String systemCode = param.getSystemCode();
        if(StringUtils.isNotEmpty(systemCode)){
            List<View> systemCodeTpls = viewList.stream().filter(view ->  systemCode.equals(view.getSystemCode())).collect(Collectors.toList());
            if(systemCodeTpls.isEmpty()){
                //不存在当前systemCode模板，取空code模板
                systemCodeTpls = viewList.stream().filter(view ->  StringUtils.isEmpty(view.getSystemCode())).collect(Collectors.toList());
            }
            if(systemCodeTpls.size() == 1){
                tplStdDTO.setTplId(MdfMapKeyUtil.getLongValue(systemCodeTpls.get(0).getTplId()));
                tplStdDTO.setBranch("systemCodeTpl");
                return tplStdDTO;
            }else if(systemCodeTpls.size()>1){
                viewList = systemCodeTpls;
            }
        }else {
            //强匹配systemCode，为空时返回未配置systemCode模板，如果所有模板都有code，则此条件无效
            List<View> emptySystemCodeTpls = viewList.stream().filter(view ->  StringUtils.isEmpty(view.getSystemCode())).collect(Collectors.toList());
            if(emptySystemCodeTpls.size() == 1){
                tplStdDTO.setTplId(MdfMapKeyUtil.getLongValue(emptySystemCodeTpls.get(0).getTplId()));
                tplStdDTO.setBranch("emptySystemCodeTpl");
                return tplStdDTO;
            }else if(emptySystemCodeTpls.size()>1){
                viewList = emptySystemCodeTpls;
            }
        }

        if( tplmode!=null){
            //存在多个模板时过滤多态模板
            final Long mode = tplmode;
            List<View> modeTpls = viewList.stream().filter(view -> (view.getTplMode() != null && mode.intValue() == view.getTplMode())).collect(Collectors.toList());
            if(modeTpls.size()==1){
                tplStdDTO.setTplId(MdfMapKeyUtil.getLongValue(modeTpls.get(0).getTplId()));
                tplStdDTO.setBranch("modeTpl");
                return tplStdDTO;
            }else if(modeTpls.size()>1){
                viewList = modeTpls;
            }
        }

        try {
            /*暂时通过初始化标记判断是否新模板管理，如果旧逻辑需要先处理交易类型数据*/
            boolean newTplInitFlag = getNewTplInitFlag(viewList);
            TplSelectBO tplSelectBO = getTplSelectBO(viewList);

            if (!newTplInitFlag) {
                //人力业务阶段处理
                Object tenantId = ExtTenantUtil.tenantId(billNo);
                if(tenantId!=null && "0".equals(tenantId.toString())) {
                    if ((StringUtils.isNotEmpty(businessStepCode) && !"null".equals(businessStepCode)) || StringUtils.isNotEmpty(transtype)) {
                        /*未初始化时，存在业务阶段数据需要走新逻辑过滤模板*/
                        View view = getSysTplByTransTypeOrBizStep(transtype, businessStepCode, viewList);
                        if (view != null && view.getTplId() != null) {
                            tplStdDTO.setTplId(Long.valueOf(String.valueOf(view.getTplId())));
                            if (view.getcExtProps() != null) {
                                Map<String, Object> cExtPropsMap = ExtPropsUtil.getExtProps(view.getcExtProps());
                                tplStdDTO.setTransType(MdfMapKeyUtil.getMapStringValueByKey("transTypeId", cExtPropsMap));
                            }
                            tplStdDTO.setBranch("beforeInitBizStepTpl");
                            return tplStdDTO;
                        }
                    }
                }
                // 优先处理交易类型的模板
                View singleTpl = getTransTypeTpl(transtype, tplSelectBO);
                if (singleTpl != null) {
                    // 如果交易类型的模板已经查询出来了，直接返回
                    tplStdDTO.setTplId(MdfMapKeyUtil.getLongValue(singleTpl.getTplId()));
                    tplStdDTO.setBranch("transTypeTpl");
                    return tplStdDTO;
                }
            }

            // 这里远程调用获取模板数据,原逻辑取了getTplIdAllOrgIdMap，现改为全部
            List<String> tplList = new ArrayList<>(tplSelectBO.getViewMap().keySet());
            MdfTplItemDTO tplItemDTO = getRemoteSingleTpl(billNo, serviceCode, transtype, orgId, businessStepCode, terminalType,param, tplList);
            if (tplItemDTO != null && tplItemDTO.getTplId() != null) {
                View singleTpl = tplSelectBO.getViewMap().get(tplItemDTO.getTplId());
                if (singleTpl != null) {
                    tplStdDTO.setTplId(MdfMapKeyUtil.getLongValue(singleTpl.getTplId()));
                    tplStdDTO.setBranch("remoteTpl");
                    if(singleTpl.getcExtProps()!=null) {
                        Map<String, Object> cExtPropsMap = ExtPropsUtil.getExtProps(singleTpl.getcExtProps());
                        tplStdDTO.setTransType(MdfMapKeyUtil.getMapStringValueByKey("transTypeId", cExtPropsMap));
                    }
                    tplStdDTO.setFilterMsg(tplItemDTO.getFilterMsg());
                    return tplStdDTO;
                }
            }

            /*原移动端逻辑*/
            if (Integer.parseInt(terminalType) > 2) {
                if (tplmode == null) {
                    tplmode = Long.parseLong(terminalType);
                }
                if (tplmode != null && tplmode > 0) {
                    Long tplid = getBillTemplateId(billNo, tplmode);
                    if (tplid != null) {
                        tplStdDTO.setTplId(tplid);
                        tplStdDTO.setBranch("sourceMobileTpl");
                        return tplStdDTO;
                    }
                }
            }

        }catch (Exception e){
            logger.error("getSingleTpl异常", e);
        }

        //没有选到模板时，取默认模板
        View defaultTpl = getDefaultTplByViewList(viewList);
        if(defaultTpl ==null){
            defaultTpl = viewList.get(0);
        }
        tplStdDTO.setBranch("defaultTpl");
        tplStdDTO.setTplId(Long.valueOf(String.valueOf(defaultTpl.getTplId())));
        if(defaultTpl.getcExtProps()!=null) {
            Map<String, Object> cExtPropsMap = ExtPropsUtil.getExtProps(defaultTpl.getcExtProps());
            tplStdDTO.setTransType(MdfMapKeyUtil.getMapStringValueByKey("transTypeId", cExtPropsMap));
        }
        return tplStdDTO;
    }
    /**
     * 获取远程模板信息
     * @return
     */
    private MdfTplItemDTO getRemoteSingleTpl(String billNo, String serviceCode, String transTypeId, String orgId,
                                             String businessStepCode, String terminalType, BillTemplateQureryParamDTO param, List<String> tplIds) {
        try {
            //MdfTemplateQueryService mdfTemplateQueryService = AppContext.getBean(MdfTemplateQueryService.class);
            MdfTemplateQueryService mdfTemplateQueryService = SpringContextHolder.getBean(MdfTemplateQueryService.class);

            // 远程模板查询服务
            MdfSingleTplQueryParam tplQueryParam = new MdfSingleTplQueryParam();
            tplQueryParam.setBillNo(billNo);
            tplQueryParam.setTplIdList(tplIds);
            // 获取业务数据中的
            tplQueryParam.setBillNo(billNo);
            tplQueryParam.setTransTypeId(transTypeId);
            tplQueryParam.setOrgId(orgId);
            tplQueryParam.setServiceCode(serviceCode);
            tplQueryParam.setUserId(null);
            tplQueryParam.setYhtTenantId(null);
            tplQueryParam.setTerminalType(terminalType);
            tplQueryParam.setBusinessStepCode(businessStepCode);

            tplQueryParam.setRefCode(param.getRefCode());
            tplQueryParam.setExtTypeId(param.getExtTypeId());
            return mdfTemplateQueryService.getRunTimeSingleTpl(tplQueryParam);
        } catch (Exception e) {
            logger.error("远程查询ucf-mdf服务多模板数据异常,先不处理,异常信息:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取交易类型模板
     *
     * @param transTypeId
     *            交易类型id
     * @param tplSelectBO
     *            模板选择业务对象
     * @return 交易类型的模板
     */
    private View getTransTypeTpl(String transTypeId, TplSelectBO tplSelectBO) {
        if (StringUtils.isEmpty(transTypeId) || tplSelectBO == null) {
            return null;
        }
        List<String> transTypeTplIds = tplSelectBO.getTransTypeIdTplIdMap().get(transTypeId);
        if (CollectionUtils.isEmpty(transTypeTplIds)) {
            return null;
        }
        // 优先取第一个吧
        String transTypeTplId = transTypeTplIds.get(0);
        // 获取指定模板的信息
        View view = tplSelectBO.getViewMap().get(transTypeTplId);
        return view;
    }

    /**
     * 获取模板选择的对象信息
     *
     * @param viewList
     *            模板列表信息
     * @return 模板选择对象
     */
    private TplSelectBO getTplSelectBO(List<View> viewList) {
        TplSelectBO tplSelectBO = new TplSelectBO();
        if (CollectionUtils.isEmpty(viewList)) {
            return tplSelectBO;
        }
        for (View view : viewList) {
            if (view == null) {
                continue;
            }
            String tplId = MdfMapKeyUtil.getStringValue(view.getTplId());
            tplSelectBO.getViewMap().put(tplId, view);
            Map<String, Object> extMap = ExtPropsUtil.getExtProps(view.getcExtProps());
            String viewOrgId = MdfMapKeyUtil.getMapStringValueByKey(FIELD_EXT_ORG_TPL_ORG_ID, extMap);
            String viewTransTypeId = MdfMapKeyUtil.getMapStringValueByKey(FIELD_EXT_TRANS_TYPE_ID, extMap);
            // 交易类型的模板
            if (StringUtils.isNotEmpty(viewTransTypeId)) {
                tplSelectBO.getTplIdTransTypeIdMap().put(tplId, viewTransTypeId);
                List<String> transTypeTplIds =
                        tplSelectBO.getTransTypeIdTplIdMap().computeIfAbsent(viewTransTypeId, k -> new ArrayList<>());
                transTypeTplIds.add(tplId);
            }
            // 组织的模板和分配的模板
            if (StringUtils.isNotEmpty(viewOrgId)) {
                // 可能有分配的模板的id
                tplSelectBO.getTplIdAllOrgIdMap().put(tplId, viewOrgId);
                List<String> orgIdTplIds =
                        tplSelectBO.getOrgIdTplIdMap().computeIfAbsent(viewOrgId, k -> new ArrayList<>());
                orgIdTplIds.add(tplId);
                if (!KEY_ORG_ID_DEFAULT.equals(viewOrgId)) {
                    // 组织级的模板id
                    tplSelectBO.getTplIdOrgIdMap().put(tplId, viewOrgId);
                }
            }
        }
        return tplSelectBO;
    }

    /**
     * 查询模板
     * @param billNo
     * @param terminalType
     * @return
     */
    private List<View> listTplByParams(String billNo, String terminalType) {
        List<View> viewList = new ArrayList<>();
        try {
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put(ConstantsProperties.PROPERTIES_BILL_NO, billNo);
            paramMap.put(ConstantsProperties.PROPERTIES_TERMINAL_TYPE, terminalType);
            viewList = getAllBillTemplateList(paramMap);
        } catch (Exception e) {
            logger.error(">>>#listTplByParams#查询模板信息出现异常,异常信息:{}", e.getMessage(), e);
        }
        return viewList;
    }

    private  List<View> getAllBillTemplateList(Map<String, Object> tplQueryParas) throws Exception{
        List<View> views =new ArrayList<>();
        if("true".equals(AppContext.getEnvConfig(CONF_ENABLE_UINION_DOMAIN)) || AppContext.shouldQueryUnion() ){
            MdfUnionBillTemplateQueryService mdfBillTemplateQueryService = AppContext.getBean(MdfUnionBillTemplateQueryService.class);
            if(mdfBillTemplateQueryService != null) {
                views = mdfBillTemplateQueryService.getAllBillTemplateList(tplQueryParas);
            }
        }else {
            MdfBillTemplateQueryService mdfBillTemplateQueryService = AppContext.getBean(MdfBillTemplateQueryService.class);
            if(mdfBillTemplateQueryService != null) {
                views = mdfBillTemplateQueryService.getAllBillTemplateList(tplQueryParas);
            }
        }
        return views;
    }
    private Map<String, Object> getExtCondition(String transtype, Map<String, Object> urlCondition){
        Map<String, Object> extCondition = urlCondition;
        if(extCondition == null) {
            extCondition = new HashMap<>();
        }
        if (StringUtils.isNotEmpty(transtype)) {
            extCondition = new HashMap<>();
            extCondition.put("transTypeId", transtype);
        }
        return extCondition;
    }

    private Long getBillTemplateId(String billno, Long tplmode) throws Exception {
        Map<String, Object> paras = new HashMap<>();
        paras.put("billno", billno);
        paras.put("tplmode", tplmode);
        Object tenantId = AppContext.getTenantId();
        tenantId = ExtTenantUtil.tenantId(tenantId, billno, ExtTenantUtil.BusinessEnums.BILL_BASE);
        paras.put("tenantId", tenantId);
        if("true".equals(AppContext.getEnvConfig(CONF_ENABLE_UINION_DOMAIN))||AppContext.shouldQueryUnion() ){
            MdfUnionBillTemplateQueryService mdfBillTemplateQueryService = AppContext.getBean(MdfUnionBillTemplateQueryService.class);
            if(mdfBillTemplateQueryService !=null) {
                return mdfBillTemplateQueryService.getBillTemplateId(paras);
            }
        }else {
            MdfBillTemplateQueryService mdfBillTemplateQueryService = AppContext.getBean(MdfBillTemplateQueryService.class);
            if(mdfBillTemplateQueryService !=null) {
                return mdfBillTemplateQueryService.getBillTemplateId(paras);
            }
        }
        return null;
    }
    /**
     * @return java.util.List<com.yonyou.ucf.mdd.common.model.uimeta.ui.View>
     * @Description 控制是否查询交易类型模板
     * @Param [billno, mode, terminalType, extProps, queryTransTypeTpl]
     * @Author DaeDalu$
     * @Date
     **/
    private List<View> getBillTemplateList(String billno, Integer mode, String terminalType, Map<String, Object> extProps) throws Exception {
        return getAllBillTemplateList(billno, mode, terminalType, extProps, true);
    }

    private List<View> getAllBillTemplateList(String billno, Integer mode, String terminalType, Map<String, Object> extProps, boolean delTransTypeTpl) throws Exception {
        Map<String, Object> paras = new HashMap<>();
        if (MapUtils.isNotEmpty(extProps)) {
            paras.putAll(extProps);
        }
        paras.put("billno", billno);
        paras.put("delTransTypeTpl", delTransTypeTpl);

        if (mode != null) {
            paras.put("mode", mode);
        }
        if (terminalType != null) {
            paras.put("terminalType", terminalType);
        }
        List<View> views = getAllBillTemplateList(paras);
        if (CollectionUtils.isEmpty(views)) {
            return views;
        }

        String transTypeId = MdfMapKeyUtil.getMapStringValueByKey("transTypeId", extProps);
        if (StringUtils.isNotEmpty(transTypeId)) {
            // 交易类型ID不为空的时候，要把交易类型的模板返回出去
            List<View> resultViewList = new ArrayList<>();
            for (View view : views) {
                if (view == null || view.getTplId() == null) {
                    continue;
                }
                Map<String, Object> cExtPropsMap = ExtPropsUtil.getExtProps(view.getcExtProps());
                String viewTransTypeId = MdfMapKeyUtil.getMapStringValueByKey("transTypeId", cExtPropsMap);
                if (transTypeId.equals(viewTransTypeId)) {
                    resultViewList.add(view);
                }
            }
            return resultViewList;
        }
        return views;
    }

    /**
     * 判断是否走过模板初始化
     * @param views
     * @return
     * @throws Exception
     */
    private boolean getNewTplInitFlag(List<View> views){

        boolean newTplInitFlag = false;
        //判断是否走过模板初始化
        for (View view : views) {
            if (view == null || view.getTplId() == null) {
                continue;
            }
            Map<String, Object> cExtPropsMap = ExtPropsUtil.getExtProps(view.getcExtProps());
            String initManageFlag = MdfMapKeyUtil.getMapStringValueByKey("initManageFlag", cExtPropsMap);
            if("1".equals(initManageFlag)){
                newTplInitFlag =true;
                break;
            }
        }
        return newTplInitFlag;
    }



    /**
     * 查询管理关系表过滤模板
     * @param billNo
     * @param views
     * @param orgId
     * @param transTypeId
     * @param terminalType
     * @param businessStepCode
     * @return
     */
    private View getDesignatedTemplate(String  billNo,List<View> views,String orgId,String transTypeId,String terminalType,String businessStepCode) {
        try {
            List<String> tplIds =new ArrayList<>();
            Map<String,View> viewMap = new HashMap<>();
            views.forEach(view -> {
                if(view!=null && view.getTplId()!=null) {
                    String tplId = String.valueOf(view.getTplId());
                    tplIds.add(tplId);
                    viewMap.put(tplId,view);
                }
            });

            MdfTemplateQueryService mdfTemplateQueryService = DubboReferenceUtils.getDubboService(MdfTemplateQueryService.class,"ucf-mdf", null);
            if(mdfTemplateQueryService == null) {
                return null;
            }
            MdfTplQueryParam mdfTplQueryParam = new MdfTplQueryParam();
            mdfTplQueryParam.setBillNo(billNo);
            mdfTplQueryParam.setTplIdList(tplIds);
            mdfTplQueryParam.setOrgId(orgId);
            mdfTplQueryParam.setTransTypeId(transTypeId);
            mdfTplQueryParam.setTerminalType(terminalType);
            /*业务阶段*/
            mdfTplQueryParam.setRefCode(businessStepCode);

            MdfTplItemDTO mdfTplItemDTO = mdfTemplateQueryService.queryDesignatedSingleTpl(mdfTplQueryParam);
            if(mdfTplItemDTO!=null && mdfTplItemDTO.getTplId()!=null){
                String tplId = mdfTplItemDTO.getTplId();
                return viewMap.get(tplId);
            }
            //如果管理关系没有查到，返null走原先逻辑
        } catch (Exception e) {
            /*为保证运行先捕获所有异常不抛出*/
            logger.error("queryDesignatedSingleTpl#异常#", e);
        }
        return null;
    }

    /**
     * 查询0租户模板下匹配交易类型和业务操作的模板
     * @param transtype
     * @param businessStepCode
     * @param views
     * @return
     */
    private View getSysTplByTransTypeOrBizStep(String transtype,String businessStepCode,List<View> views ){
        //转换交易类型
        String transTypeSourceId = null;
        if(StringUtils.isNotEmpty(transtype)) {
            try {
                MdfTemplateQueryService mdfTemplateQueryService = DubboReferenceUtils.getDubboService(MdfTemplateQueryService.class, "ucf-mdf", null);
                transTypeSourceId = mdfTemplateQueryService.queryTransTypeSourceId(transtype);
            } catch (MdfIrisException e) {
                /*为保证运行先捕获所有异常不抛出*/
                logger.error("MdfTemplateQueryService#queryTransTypeSourceId#异常#", e);
            }
        }
        if (StringUtils.isEmpty(transTypeSourceId)) {
            //如果没有查到转换类型，还是拿原交易类型匹配
            transTypeSourceId = transtype;
        }
        List<View> transTypeViewList = new ArrayList<>();
        List<View> defaultTansViewList = new ArrayList<>();
        for (View view : views) {
            if (view == null || view.getTplId() == null) {
                continue;
            }
            Map<String, Object> cExtPropsMap = ExtPropsUtil.getExtProps(view.getcExtProps());
            String viewTransTypeId = MdfMapKeyUtil.getMapStringValueByKey("transTypeId", cExtPropsMap);
            //默认交易类型模板
            if (StringUtils.isEmpty(viewTransTypeId)) {
                defaultTansViewList.add(view);
            }
            //当前交易类型模板
            if (StringUtils.isNotEmpty(transtype) && StringUtils.isNotEmpty(viewTransTypeId) && (transtype.equals(viewTransTypeId) || transTypeSourceId.equals(viewTransTypeId))){
                transTypeViewList.add(view);
            }
        }
        //只存在0租户模板时，直接匹配
        if(StringUtils.isNotEmpty(businessStepCode)) {
            //在当前交易类型匹配
            if(CollectionUtils.isNotEmpty(transTypeViewList)){
                View view = filterBizStepViews(businessStepCode, transTypeViewList);
                if(view !=null){
                    return view;
                }
            }
            //在默认交易类型匹配
            if(CollectionUtils.isNotEmpty(defaultTansViewList)) {
                View view = filterBizStepViews(businessStepCode, defaultTansViewList);
                if(view !=null){
                    return view;
                }
            }
        }
        if(CollectionUtils.isNotEmpty(transTypeViewList)){
            View defaultTpl = getDefaultTplByViewList(transTypeViewList);
            if(defaultTpl!=null){
                return defaultTpl;
            }else {
                return transTypeViewList.get(0);
            }
        }
        if(CollectionUtils.isNotEmpty(defaultTansViewList)){
            View defaultTpl = getDefaultTplByViewList(defaultTansViewList);
            if(defaultTpl!=null){
                return defaultTpl;
            }
        }
        return null;
    }
    /**
     * 获取模板信息中的默认模板
     *
     * @param viewList
     *            模板信息列表
     * @return
     */
    private View getDefaultTplByViewList(List<View> viewList) {
        if (CollectionUtils.isEmpty(viewList)) {
            return null;
        }
        for (View view : viewList) {
            if (view == null) {
                continue;
            }
            Boolean defaultTpl = view.isDefault();
            if (defaultTpl != null && defaultTpl) {
                return view;
            }
        }
        return null;
    }
    private View filterBizStepViews(String businessStepCode, List<View> views) {
        for (View view : views) {
            if (view == null || view.getTplId() == null) {
                continue;
            }
            Map<String, Object> cExtPropsMap = ExtPropsUtil.getExtProps(view.getcExtProps());
            String stepCodeDb = MdfMapKeyUtil.getMapStringValueByKey("businessStepCode", cExtPropsMap);
            if (stepCodeDb != null && stepCodeDb.equals(businessStepCode)) {
                return view;
            }
        }
        return null;
    }

    /**
     * 列出所有模板信息，带过滤
     *
     * @param billno
     *            单据编码
     * @param mode
     *            模板类型
     * @param terminalType
     *            终端类型
     * @param extCondition
     *            交易类型数据
     * @param refCode
     *            指定档案的refCode(domian.code的形式)
     * @param extTypeId
     *            指定档案id
     * @return
     * @throws Exception
     */
    private List<View> listAssignedTpl(String billno, Integer mode, String terminalType, Map<String, Object> extCondition,
                                       String refCode, String extTypeId) throws Exception {
        List<View> allTplList = getAllBillTemplateList(billno, mode, terminalType, extCondition, true);
        if (allTplList == null || allTplList.size() == 0) {
            return new ArrayList<>();
        }

        if (allTplList.size() == 1){
            return allTplList;
        }

        String orgId = AppContext.getThreadContext(MddConstants.PARAM_ORG_ID);
        String serviceCode = AppContext.getThreadContext(MddConstants.PARAM_SERVICE_CODE);
        String token = InvocationInfoProxy.getYhtAccessToken();
        String userId = AppContext.getCurrentUser().getYhtUserId();
        String yhtTenantId = AppContext.getCurrentUser().getYhtTenantId();
        Map<String,String> orgTplDataMap = new HashMap<>();
        // 这里就是要留一个看看
        Map<String,String> transTypeDataMap = new HashMap<>();
        Map<String,String> assignTplDataMap = new HashMap<>();
        Map<String,View> viewMap = new HashMap<>();

        Iterator<View> iterator = allTplList.iterator();
        while (iterator.hasNext()){
            View view = iterator.next();
            String tplId = MdfMapKeyUtil.getStringValue(view.getTplId());
            viewMap.put(tplId, view);
            String extProps = view.getcExtProps();
            Map<String, Object> extMap = ExtPropsUtil.getExtProps(extProps);
            String orgTplOrgId = MdfMapKeyUtil.getMapStringValueByKey(FIELD_EXT_ORG_TPL_ORG_ID, extMap);
            String transTypeId = MdfMapKeyUtil.getMapStringValueByKey(FIELD_EXT_TRANS_TYPE_ID, extMap);
            String nexusType = MdfMapKeyUtil.getMapStringValueByKey(FIELD_EXT_NEXUS_TYPE, extMap);
            // 交易类型的模板
            if (StringUtils.isNotEmpty(transTypeId)) {
                transTypeDataMap.put(tplId, transTypeId);
                // 去除交易类型的分配信息
            }
            // 组织的模板和分配的模板
            if (StringUtils.isNotEmpty(orgTplOrgId)) {
                assignTplDataMap.put(tplId, orgTplOrgId);
                if (!KEY_ORG_ID_DEFAULT.equals(orgTplOrgId)){
                    orgTplDataMap.put(tplId, orgTplOrgId);
                }
            }
        }

        MdfTemplateLoadService mdfTemplateLoadService = AppContext.getBean(MdfTemplateLoadService.class);
        MdfTemplateAssignService mdfTemplateAssignService = AppContext.getBean(MdfTemplateAssignService.class);

        // 是否有用户级模板数据
        boolean hasUserRoleTpl = false;

        // 启用按指定类型分配，这里先不动，后期再处理
        String extTypeTemplateEnable =AppContext.getEnvConfig(MddConstants.CONF_ENABLE_TEMPLATE_ASSIGN_EXTTYPE);
        if ("true".equals(extTypeTemplateEnable) && mdfTemplateAssignService != null) {
            try {
                TemplateAssignQueryParamDTO templateAssignQueryParamDTO = new TemplateAssignQueryParamDTO();
                templateAssignQueryParamDTO.setBillno(billno);
                templateAssignQueryParamDTO.setTenantId(yhtTenantId);
                templateAssignQueryParamDTO.setRefCode(refCode);
                templateAssignQueryParamDTO.setExtTypeId(extTypeId);
                List<TemplateAssignDTO> templateAssignDTOList =
                        mdfTemplateAssignService.listTemplateAssign(templateAssignQueryParamDTO);
                if (templateAssignDTOList != null && templateAssignDTOList.size() > 0) {
                    Map<String, List<TemplateAssignDTO>> mapTplIdToAssignDTO = new HashMap<>();
                    for (TemplateAssignDTO templateAssignDTO : templateAssignDTOList) {
                        List<TemplateAssignDTO> templateAssignDTOS = new ArrayList<>();
                        if (mapTplIdToAssignDTO.containsKey(templateAssignDTO.getTplId())) {
                            templateAssignDTOS = mapTplIdToAssignDTO.get(templateAssignDTO.getTplId());
                        }
                        templateAssignDTOS.add(templateAssignDTO);
                        mapTplIdToAssignDTO.put(templateAssignDTO.getTplId(), templateAssignDTOS);
                    }

                    List<View> tplListExtType = new ArrayList<>();
                    allTplList.forEach(view -> {
                        boolean isAdd = false;
                        if (mapTplIdToAssignDTO.containsKey(view.getTplId().toString())) {
                            List<TemplateAssignDTO> templateAssignDTOS =
                                    mapTplIdToAssignDTO.get(view.getTplId().toString());
                            view.setAssignedTime(getLastAssignedTime(templateAssignDTOS));
                            String extTypeIds = getExtTypeIds(templateAssignDTOS);
                            if (StringUtils.isNotBlank(extTypeIds)) {
                                view.setExtTypeId(extTypeIds);
                                isAdd = true;
                            }
                            String firstRefCode = getFirstRefCode(templateAssignDTOS);
                            if (StringUtils.isNotBlank(firstRefCode)) {
                                view.setRefCode(firstRefCode);
                                isAdd = true;
                            }
                            if (isAdd) {
                                tplListExtType.add(view);
                            }
                        }
                    });

                    if (tplListExtType.size() > 0) {
                        return tplListExtType;
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        // 处理分配的模板，需要过滤
        if (MapUtils.isNotEmpty(assignTplDataMap) && mdfTemplateAssignService != null){
            try {
                TemplateAssignQueryParamDTO assignQueryParam = new TemplateAssignQueryParamDTO();
                assignQueryParam.setBillno(billno);
                assignQueryParam.setUserId(userId);
                assignQueryParam.setTenantId(yhtTenantId);
                ITenantRoleUserService tenantRoleUserService = AppContext.getBean(ITenantRoleUserService.class);
                List<TenantRole> tenantRoles = tenantRoleUserService.findRolesByUserId(userId, yhtTenantId, "diwork");
                List<String> roleList = new ArrayList<>();
                if (tenantRoles != null && tenantRoles.size() > 0) {
                    tenantRoles.forEach(item -> {
                        roleList.add(item.getRoleId());
                    });
                    assignQueryParam.setRoleIds(roleList);
                }

                // 获取分配的模板信息
                List<TemplateAssignDTO> templateAssignDTOList = mdfTemplateAssignService.listTemplateAssign(assignQueryParam);
                if (CollectionUtils.isNotEmpty(templateAssignDTOList)) {
                    Map<String, List<TemplateAssignDTO>> tplIdToAssignMap = new HashMap<>();
                    for (TemplateAssignDTO templateAssignDTO : templateAssignDTOList) {
                        String tplId = templateAssignDTO.getTplId();
                        View view = viewMap.get(tplId);
                        if (view != null) {
                            if(userId.equals(templateAssignDTO.getUserId())){
                                view.setUserId(templateAssignDTO.getUserId());
                            }
                            view.setRoleId(templateAssignDTO.getRoleId());
                            // 取最大的时间写入
                            Date oldDate = view.getAssignedTime();
                            Date newDate = templateAssignDTO.getAssignedTime();
                            if (oldDate == null) {
                                view.setAssignedTime(newDate);
                            } else {
                                if (newDate != null && newDate.getTime() > oldDate.getTime()) {
                                    view.setAssignedTime(newDate);
                                }
                            }
                            hasUserRoleTpl = true;
                        }
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        if (hasUserRoleTpl){
            // 当存在用户和角色级模板时，不需要有选择组织切换模板的动作，直接去除
            return allTplList;
        }

        if (MapUtils.isNotEmpty(orgTplDataMap) && mdfTemplateLoadService != null){
            // 组织级模板处理
            List<TemplateOrgDTO> templateOrgDTOList = null;
            try {
                if (StringUtils.isNotEmpty(orgId)) {
                    templateOrgDTOList = mdfTemplateLoadService.listTemplateOrgByBillNoAndOrgIdAndDefaultStatus(billno, yhtTenantId, orgId, true);
                } else {
                    templateOrgDTOList = mdfTemplateLoadService.listTemplateOrgByBillNoAndDefaultStatus(billno, yhtTenantId, userId, token, serviceCode, true);
                }
                if (CollectionUtils.isNotEmpty(templateOrgDTOList)) {
                    for (TemplateOrgDTO templateOrgDTO : templateOrgDTOList) {
                        String tplId = templateOrgDTO.getPkTemp();
                        View view = viewMap.get(tplId);
                        if (view != null){
                            view.setOrgId(templateOrgDTO.getOrgId());
                            view.setOrgName(templateOrgDTO.getOrgName());
                            view.setDefault(true);
                        }
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        return allTplList;
    }

    private Date getLastAssignedTime(List<TemplateAssignDTO> templateAssignDTOS) {
        Date assignedTime = null;
        for (TemplateAssignDTO templateAssignDTO : templateAssignDTOS) {
            if (assignedTime == null || assignedTime.before(templateAssignDTO.getAssignedTime())) {
                assignedTime = templateAssignDTO.getAssignedTime();
            }
        }
        return assignedTime;
    }
    private String getExtTypeIds(List<TemplateAssignDTO> templateAssignDTOS) {
        StringBuilder builder = new StringBuilder();
        for (TemplateAssignDTO templateAssignDTO : templateAssignDTOS) {
            if (StringUtils.isNotBlank(templateAssignDTO.getExtTypeId())) {
                builder.append(templateAssignDTO.getExtTypeId()).append(",");
            }
        }
        if (builder.length() > 0) {
            return builder.subSequence(0, builder.length() - 1).toString();
        } else {
            return null;
        }
    }

    private String getFirstRefCode(List<TemplateAssignDTO> templateAssignDTOS) {
        if (templateAssignDTOS.size() > 0) {
            return templateAssignDTOS.get(0).getRefCode();
        } else {
            return null;
        }
    }

    private String getUserIds(List<TemplateAssignDTO> templateAssignDTOS) {
        StringBuilder builder = new StringBuilder();
        for (TemplateAssignDTO templateAssignDTO : templateAssignDTOS) {
            if (StringUtils.isNotBlank(templateAssignDTO.getUserId())) {
                builder.append(templateAssignDTO.getUserId()).append(",");
            }
        }
        if (builder.length() > 0) {
            return builder.subSequence(0, builder.length() - 1).toString();
        } else {
            return null;
        }
    }

    private String getRoleIds(List<TemplateAssignDTO> templateAssignDTOS) {
        StringBuilder builder = new StringBuilder();
        for (TemplateAssignDTO templateAssignDTO : templateAssignDTOS) {
            if (StringUtils.isNotBlank(templateAssignDTO.getRoleId())) {
                builder.append(templateAssignDTO.getRoleId()).append(",");
            }
        }
        if (builder.length() > 0) {
            return builder.subSequence(0, builder.length() - 1).toString();
        } else {
            return null;
        }
    }

}
